package controllers

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/httplib"
	"huxiaopang/models"
	"io"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"
)

type PayController struct {
	ApiBaseController
}

//生成随机字符串
func GetRandomString(l int) string {   
   str := "0123456789"
   bytes := []byte(str)
   result := []byte{}
   r := rand.New(rand.NewSource(time.Now().UnixNano()))
   for i := 0; i < l; i++ {
      result = append(result, bytes[r.Intn(len(bytes))])
   }
   return string(result)
}

// @router /order [post]
func (this *PayController) Order() {
	var storeName string
	bean := BaseBean{}
	uuid := this.GetString("uuid")
	channel := this.GetString("channel")
	amount := this.GetString("amount")

	beego.Debug("uuid:" + uuid)
	beego.Debug("channel:" + channel)
	beego.Debug("amount:" + amount)

	if len(uuid) == 0 {
		bean.Code = "-1"
		bean.Message = "uuid不能为空"

		this.Data["json"] = bean
		this.ServeJSON()
		return
	}

	if len(channel) == 0 {
		bean.Code = "-1"
		bean.Message = "channel不能为空"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}

	if len(amount) == 0 {
		bean.Code = "-1"
		bean.Message = "amount不能为空"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}


	tableNumberData := models.TableNumberData{}
	tableNumberData.Uuid = uuid
	if err := tableNumberData.Read("Uuid");  err != nil && err!=orm.ErrNoRows{
		bean.Code = "-1"
		bean.Message = "系统繁忙"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}else if err == orm.ErrNoRows{
		//错误
		bean.Code = "-1"
		bean.Message = "uuid错误"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	} else {
		storePermissionData := models.StorePermissionData{}
		storePermissionData.StoreCode = tableNumberData.StoreCode
		if err := storePermissionData.Read("StoreCode"); err == nil {
			storeName = storePermissionData.StoreName
		}
	}

	//先插入订单，然后调用H5接口
	tradeBean := models.TradeData{}
	tradeBean.TradeChannel = channel
	tradeBean.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	downTradeNo := time.Now().Format("20060102150405") + GetRandomString(10)
	tradeBean.DownTradeNo = downTradeNo
	tradeBean.HasPush = "N"
	tradeBean.StoreCode = tableNumberData.StoreCode
	tradeBean.StoreName = storeName
	tradeBean.TableCode = tableNumberData.TableCode
	tradeBean.PayAmount, _ = strconv.Atoi(amount)
	tradeBean.TradeStatus = "NOTPAY"
	tradeBean.Insert()

	var paramString string
	paramsMap := make(map[string]string)
	paramsMap["app_id"] = "148053935510122"
	paramsMap["timestamp"] = tradeBean.CreateTime
	paramsMap["version"] = "v46"
	paramsMap["store_code"] = tableNumberData.StoreCode
	paramsMap["dev_id"] = tableNumberData.TableCode
	paramsMap["pay_channel"] = channel
	paramsMap["amount"] = amount
	paramsMap["undiscountable_amount"] = "0"
	paramsMap["down_trade_no"] = tradeBean.DownTradeNo
	paramsMap["back_notify_url"] = HOST + "notify/notifyresult"
	paramsMap["front_url"] = HOST + "pay/paysuccess"

	sign(paramsMap)
	for key, value := range paramsMap {
		if(key != "undiscountable_amount"){
			paramString += key
			paramString += "="
			paramString += value
			paramString += "&"
		}
	}
	redirect_url := fmt.Sprintf("http://open.guangfen.net/api/v46/pay/h5?%s", paramString)
	beego.Debug(redirect_url)
		this.Data["json"] = map[string]interface{}{
		"code": "0",
		"msg":  "SUCCESS",
		"data": redirect_url,
	}
	this.ServeJSON()
	return

	/*
	h5ResultBean := H5ResultBean{}
	beego.Debug(req.String())
	if err := req.ToJSON(&h5ResultBean); err != nil {
		//下单失败
		log.Fatal("err msg:", err)
		//下单失败
		bean.Code = "-1"
		bean.Message = err.Error()
		this.Data["json"] = bean
		this.ServeJSON()
		return
	} else {
		beego.Debug(h5ResultBean)
		if h5ResultBean.Code == "-1" {
			//下单失败
			bean.Code = "-1"
			bean.Message = h5ResultBean.Msg
			this.Data["json"] = bean
			this.ServeJSON()
			return
		} else {
			data := models.TradeData{}
			data.DownTradeNo = downTradeNo
			if err := data.Read("DownTradeNo"); err == nil {
				data.TradeNo = h5ResultBean.TradeNo
				data.UpTradeNo = h5ResultBean.UpTradeNo
				//orderResultBean.UpTradeNo = tradeBeanResult.Data.UpTradeNo
				//orderResultBean.PayInfo = tradeBeanResult.PayInfo
				//orderResultBean.TradeNo = tradeBeanResult.Data.TradeNo
				data.Update("TradeNo", "UpTradeNo")
			}
			this.Data["json"] = map[string]interface{}{
				"code": "0",
				"msg":  "SUCCESS",
				"data": "",
			}
			this.ServeJSON()
			return
		}
	}
	*/
}

func sign(params map[string]string) map[string]string{
	// To store the keys in slice in sorted order
	var result string
	var keys []string
	for k := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	// To perform the opertion you want
	for _, k := range keys {
		result += k
		result += "="
		result += params[k]
		result += "&";
	}
	result += "APP_SECRET=" + APP_SECRET;
	beego.Debug("result:" + result)
	result = md5V(result)
	params["sign"] = result
	return params
}


func md5V(data string) string {
	m := md5.New()
	io.WriteString(m, data)
	x := hex.EncodeToString(m.Sum(nil))
	return strings.ToUpper(x)
}

// @router /paysuccess [get]
func (this *PayController) PaySuccess() {
	//var queryTradeBean QueryOrderBean
	beego.Debug("支付完成paysuccess")
	bean := BaseBean{}
	code := this.GetString("code")
	userAgent := this.Ctx.Request.Header.Get("User-Agent")
	//支付失败
	if(code == "-1"){
		if len(userAgent) != 0 && strings.Contains(userAgent, "AlipayClient") {
			this.Data["err_msg"] = this.GetString("msg")
			this.TplName="pay_fail.html"
			return
		}else if len(userAgent) != 0 && strings.Contains(userAgent, "MicroMessenger") {
			this.Data["err_msg"] = this.GetString("msg")
			this.TplName="wx_fail.html"
			return
		}
	}

	downTradeNo := this.GetString("down_trade_no")
	if len(downTradeNo) == 0 {
		bean.Code = "-1"
		bean.Message = "down_trade_no不能为空"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}

	tradeData := models.TradeData{}
	tradeData.DownTradeNo = downTradeNo
	if err := tradeData.Read("DownTradeNo");  err != nil && err!=orm.ErrNoRows{
		this.Data["err_msg"] = "系统繁忙"
		this.TplName="err.html"
		return
	}else if err == orm.ErrNoRows{
		this.Data["err_msg"] = "没有该订单"
		this.TplName="err.html"
		return
	}else {
		if(tradeData.TradeStatus == "NOTPAY"){
			beego.Debug("订单查询")
			//查询不到，调用查询接口，同步数据
			req := httplib.Post(GUANG_FEN_HOST + "pay/query")

			paramsMap := make(map[string]string)
			paramsMap["app_id"] = "148053935510122"
			paramsMap["timestamp"] = time.Now().Format("2006-01-02 15:04:05")
			paramsMap["version"] = "v46"
			paramsMap["store_code"] = tradeData.StoreCode
			//paramsMap["trade_no"] = tradeData.TradeNo
			paramsMap["trade_no_type"] = "2"
			paramsMap["pay_channel"] = tradeData.TradeChannel
			paramsMap["down_trade_no"] = tradeData.DownTradeNo
			sign(paramsMap)
			for key, value := range paramsMap {
				req.Param(key, value)
			}
			payOrderQueryResult := PayOrderQueryResult{}
			if err := req.ToJSON(&payOrderQueryResult); err != nil && err!=orm.ErrNoRows{
				bean.Code = "-1"
				bean.Message = "系统繁忙"
				this.Data["json"] = bean
				this.ServeJSON()
				return
			}else if err == orm.ErrNoRows{
				//查询失败
				beego.Debug(err)
				bean.Code = "-1"
				bean.Message = "查询失败"
				this.Data["json"] = bean
				this.ServeJSON()
				return
			} else {
				beego.Debug(payOrderQueryResult)
				if payOrderQueryResult.Code == "-1" {
					//查询失败
					bean.Code = "-1"
					bean.Message = "查询订单失败"
					this.Data["json"] = bean
					this.ServeJSON()
					return
				} else {
					this.Data["buyer_amount"] = float64(payOrderQueryResult.Data.BuyerAmount)/100
					this.Data["store_name"] = payOrderQueryResult.Data.StoreName
					this.Data["table_code"] = tradeData.TableCode
					this.Data["trade_no"] = payOrderQueryResult.Data.TradeNo
					this.Data["pay_time"] = payOrderQueryResult.Data.TimeEnd
					if(tradeData.TradeChannel == "WECHAT"){
						this.TplName="wxsuccess.html"						
					}else {
						this.TplName="success.html"
					}
					return
				}
			}
		}else {
			this.Data["buyer_amount"] = float64(tradeData.BuyerAmount)/100
			this.Data["store_name"] = tradeData.StoreName
			this.Data["table_code"] = tradeData.TableCode
			this.Data["trade_no"] = tradeData.TradeNo
			this.Data["pay_time"] = tradeData.PayTime
			if(tradeData.TradeChannel == "WECHAT"){
				this.TplName="wxsuccess.html"						
			}else {
				this.TplName="success.html"
			}
			return
		}
	}
}

// @router /queryorder [post]
func (this *PayController) QueryOrder() {
	bean := BaseBean{}
	tradeNo := this.GetString("trade_no")
	beego.Debug(tradeNo)
	if len(tradeNo) == 0 {
		bean.Code = "-1"
		bean.Message = "trade_no不能为空"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}

	tradeData := models.TradeData{}
	tradeData.TradeNo = tradeNo

	if err := tradeData.Read("TradeNo"); err != nil && err!=orm.ErrNoRows{
		bean.Code = "-1"
		bean.Message = "系统繁忙"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}else if err == orm.ErrNoRows{
		bean.Code = "-1"
		bean.Message = "未找到订单"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	} else {
		var queryTradeBean QueryOrderBean
		queryTradeBean.TradeNo = tradeData.TradeNo
		queryTradeBean.UpTradeNo = tradeData.UpTradeNo
		queryTradeBean.DownTradeNo = tradeData.DownTradeNo
		queryTradeBean.StoreCode = tradeData.StoreCode
		queryTradeBean.TableCode = tradeData.TableCode
		queryTradeBean.StoreName = tradeData.StoreName
		queryTradeBean.TradeStatus = tradeData.TradeStatus
		queryTradeBean.TradeChannel = tradeData.TradeChannel
		queryTradeBean.PayAmount = tradeData.PayAmount
		queryTradeBean.ReceiptAmount = tradeData.ReceiptAmount
		queryTradeBean.BuyerAmount = tradeData.BuyerAmount
		queryTradeBean.BuyerUserId = tradeData.BuyerUserId
		queryTradeBean.BuyerUserName = tradeData.BuyerUserName
		queryTradeBean.OpenId = tradeData.OpenId
		queryTradeBean.SubOpenId = tradeData.SubOpenId
		queryTradeBean.RawData = tradeData.RawData
		queryTradeBean.CreateTime = tradeData.CreateTime
		queryTradeBean.PayTime = tradeData.PayTime
		this.Data["json"] = map[string]interface{}{
			"code": "0",
			"msg":  "SUCCESS",
			"data": queryTradeBean,
		}
		this.ServeJSON()
		return
	}

}

// @router /updatepush [post]
func (this *PayController) UpdatePush() {
	bean := BaseBean{}
	tradeNo := this.GetString("trade_no")
	beego.Debug(tradeNo)
	if len(tradeNo) == 0 {
		bean.Code = "-1"
		bean.Message = "trade_no不能为空"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	}

	tradeData := models.TradeData{}
	tradeData.TradeNo = tradeNo
	if err := tradeData.Read("TradeNo"); err != nil {
		bean.Code = "-1"
		bean.Message = "该订单不存在"
		this.Data["json"] = bean
		this.ServeJSON()
		return
	} else {
		tradeData.HasPush = "Y"
		tradeData.Update("HasPush")
	}

	this.Data["json"] = map[string]interface{}{
		"code": "0",
		"msg":  "SUCCESS",
		"data": "更新成功",
	}
	this.ServeJSON()
	return

}
